use std::fs::File;
use std::io::prelude::*;
use std::net::Shutdown;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpListener;
use tokio::prelude::*;
// async fn handle_connection(mut stream: TcpStream) {
//     let mut buffer = [0; 512];
//     let n = stream.peek(&mut buffer).await?;

//     let get = b"GET / HTTP/1.1\r\n";
//     let sleep = b"GET /sleep HTTP/1.1\r\n";
//     let (status_line, filepath) = if buffer.starts_with(get) {
//         ("HTTP/1.1 200 OK\r\n\r\n", "./html/hello.html")
//     } else if buffer.starts_with(sleep) {
//         // thread::sleep(Duration::from_secs(5));
//         ("HTTP/1.1 200 OK\r\n\r\n", "./html/hello.html")
//     } else {
//         ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "./html/404.html")
//     };

//     let mut file = File::open(filepath).unwrap();
//     let mut contents = String::new();

//     file.read_to_string(&mut contents).unwrap();
//     let response = format!("{}{}", status_line, contents);

//     stream.write(response.as_bytes());
//     stream.flush();
//     println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
// }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut listener = TcpListener::bind("127.0.0.1:8080").await?;

    loop {
        let (mut socket, _) = listener.accept().await?;

        tokio::spawn(async move {
            let mut buf = [0; 1024];

            // In a loop, read data from the socket and write the data back.
            loop {
                let _n = match socket.read(&mut buf).await {
                    // socket closed
                    Ok(n) if n == 0 => return,
                    Ok(n) => n,
                    Err(e) => {
                        println!("failed to read from socket; err = {:?}", e);
                        return;
                    }
                };
                println!("{:?}", String::from_utf8_lossy(&buf[..]));
                let get = b"GET / HTTP/1.1\r\n";
                let sleep = b"GET /sleep HTTP/1.1\r\n";
                let (status_line, filepath) = if buf.starts_with(get) {
                    ("HTTP/1.1 200 OK\r\n\r\n", "./html/hello.html")
                } else if buf.starts_with(sleep) {
                    // thread::sleep(Duration::from_secs(5));
                    ("HTTP/1.1 200 OK\r\n\r\n", "./html/hello.html")
                } else {
                    ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "./html/404.html")
                };
                let mut file = File::open(filepath).unwrap();
                let mut contents = String::new();
                file.read_to_string(&mut contents).unwrap();
                let response = format!("{}{}", status_line, contents);
                // socket.write_all(response.as_bytes()).await?;
                // Write the data back
                if let Err(e) = socket.write_all(response.as_bytes()).await {
                    println!("failed to write to socket; err = {:?}", e);
                    return;
                }
                socket.flush().await.unwrap();
                socket.shutdown(Shutdown::Write).unwrap();
            }
        });
    }
}
